<?php

namespace app\Http\Controllers\admins;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class Files extends Controller
{
    // 表单
    private function form($field = [])
    {
        $form = [
            ['label' => '重命名', 'name' => 'file_name', 'type' => 'textarea', 'verify' => 'required'],
        ];
        if ($field) {
            if (count($field) === count($field, 1)) {
                array_push($form, $field);
            } else {
                $form = array_merge($form, $field);
            }
        }
        return $form;
    }

    public function index(Request $request)
    {
        if ($request->ajax()) {
            // $page = $request->page ?? 1;
            $limit = $request->limit ?? 10;
            $db = DB::table('files');
            // 搜索
            if (isset($request->search) && $request->search) {
                foreach ((array)$request->search as $k => $v) {
                    if ($v) $db = $db->where($k, 'like', "%{$v}%");
                }
            }
            $db = $db->orderBy('id', 'desc');
            $data['count'] = $db->count();
            // 分页
            $db = $db->paginate($limit)->items();
            if ($data['count']) {
                $data['code'] = 0;
            } else {
                $data['code'] = 1;
                $data['msg'] = '暂无记录';
            }
            $data['data'] = array_map(function ($item) {
                $item->preview = Storage::exists($item->path) ? (preg_match('/public\/.+?\.(gif|jpg|jpeg|png|bmp|webp|psd|svg|tiff)$/i', $item->path) ? '<img src="' . Storage::url($item->path) . '" style="width:50px;height:30px;" />' : substr(strrchr($item->path, '.'), 1)) : '';
                $item->size = Storage::exists($item->path) ? round(Storage::size($item->path)/1024*100)/100 . ' KB' : '';
                $item->url = Storage::exists($item->path) ? Storage::url($item->path) : '';
                $item->time = date('Y-m-d H:i:s', $item->time);
                $item->status = $item->status ? '未使用' : '正常';
                return $item;
            }, $db);
            return json_encode($data);
        }
        // 构建搜索表单
        $form = [
            ['label' => '搜索ID', 'name' => 'id', 'layui' => 'inline', 'placeholder' => '请输入'],
            ['label' => '文件名', 'name' => 'file_name', 'layui' => 'inline', 'placeholder' => '请输入'],
            ['label' => '筛选', 'name' => 'path', 'type' => 'select', 'layui' => 'inline', 'value' => '', 'options' => ['' => '&mdash; 全部 &mdash;', '/images/' => '图片', '/files/' => '文件']],
            ['type' => 'submit', 'filter' => 'search', 'layui' => 'inline', 'value' => '<i class="layui-icon layui-icon-search"></i>']
        ];
        $data['search'] = $this->build_form($form);
        $data['title'] = '文件列表';
        $data['prefix'] = '/admins/files';
        // 检查上传类型和大小
        $setting = DB::table('setting')->where('names', 'setting')->first();
        $exts = 'gif|jpg|jpeg|png';
        $size = 2048;
        if ($setting && isset($setting->values)) {
            $values = json_decode($setting->values);
            $exts = $values->exts ?? 'gif|jpg|jpeg|png';
            $size = $values->size ?? 2048;
        }
        $data['exts'] = $exts;
        $data['size'] = $size;
        return view('/admins/files/index', $data);
    }

    public function add()
    {
        // 检查上传类型和大小
        $setting = DB::table('setting')->where('names', 'setting')->first();
        $exts = 'gif|jpg|jpeg|png';
        $size = 2048;
        if ($setting && isset($setting->values)) {
            $values = json_decode($setting->values);
            $exts = $values->exts ?? 'gif|jpg|jpeg|png';
            $size = $values->size ?? 2048;
        }
        $data['exts'] = $exts;
        $data['size'] = $size;
        $data['title'] = '文件添加';
        $data['prefix'] = '/admins/files';
        return view('/admins/files/add', $data);
    }

    // 计算孤立文件
    public function calc()
    {
        $names = [];
        // 设置中是否引用文件
        $settings = DB::table('setting')->select('values')->get()->all();
        foreach ($settings as $obj) {
            if (preg_match_all('#["\'](/storage/.+?\.[^"\']*)["\']#i', str_replace('\\', '', $obj->values), $matches)) {
                foreach (array_unique($matches[1]) as $match) {
                    $names[] = basename($match);
                }
            }
        }
        // 用户是否上传图像
        $avatars = DB::table('admin')->select('avatar')->get()->all();
        foreach ($avatars as $obj) {
            if (preg_match_all('#(/storage/.+?\.[^"\']*)#i', str_replace('\\', '', $obj->avatar), $matches)) {
                foreach (array_unique($matches[1]) as $match) {
                    $names[] = basename($match);
                }
            }
        }
        // 文章缩略图是否引用文件
        $thumbs = DB::table('article')->select('thumb')->get()->all();
        foreach ($thumbs as $obj) {
            if (preg_match_all('#(/storage/.+?\.[^"\']*)#i', str_replace('\\', '', $obj->thumb), $matches)) {
                foreach (array_unique($matches[1]) as $match) {
                    $names[] = basename($match);
                }
            }
        }
        // 文章内容是否上传引用文件
        $contents = DB::table('article')->select('content')->get()->all();
        foreach ($contents as $obj) {
            if (preg_match_all('#["\'](/storage/.+?\.[^"\']*)["\']#i', str_replace('\\', '', $obj->content), $matches)) {
                foreach (array_unique($matches[1]) as $match) {
                    $names[] = basename($match);
                }
            }
        }
        $names = array_unique($names);
        $files = DB::table('files')->select('id', 'file_name')->get()->all();
        $ids1 = $ids2 = [];
        foreach ($files as $obj) {
            if (in_array($obj->file_name, $names)) {
                $ids1[] = $obj->id;
            } else {
                $ids2[] = $obj->id;
            }
        }
        DB::table('files')->whereIn('id', $ids1)->update(['status' => 0]);
        DB::table('files')->whereIn('id', $ids2)->update(['status' => 1]);
        return $this->errMsg(0, '共找到 ' . count($ids2) . ' 个孤立文件');
    }

    public function edit(Request $request)
    {
        $id = (int)$request->id;
        if (!$id) return $this->errMsg(1, '数据错误');
        $value = DB::table('files')->where('id', $id)->first();
        $form = $this->form([
            ['name' => 'id', 'type' => 'hidden', 'value' => $id],
            ['name' => 'path', 'type' => 'hidden', 'value' => $value->path],
            ['type' => 'submit', 'value' => '保存'],
            ['type' => 'button', 'value' => '取消', 'filter' => 'cancel', 'btn' => 'primary']
        ]);
        $args = ['url' => '/admins/files/save_edit', 'reload' => 'dataTable'];
        $data['title'] = '编辑';
        $data['form'] = $this->build_form($form, $value);
        $data['script'] = $this->build_script($form, $args);
        return view('/admins/files/edit', $data);
    }

    public function save_edit(Request $request)
    {
        $id = (int)$request->id;
        $path = $request->path;
        if (!$id || !$path) return $this->errMsg(1, '数据错误');
        $data = $this->check($this->form(), $request);
        if (!is_array($data)) return $data;
        $file_name = $data['file_name'];
        // 检查扩展名
        if ($ext = substr(strrchr($path, '.'), 1)) {
            if ($ext !== substr(strrchr($file_name, '.'), 1))
                return $this->errMsg(1, '不能修改扩展名 ' . $ext);
        }
        // 检查文件类型
        $setting = DB::table('setting')->where('names', 'setting')->first();
        $exts = 'gif|jpg|jpeg|png';
        if ($setting && isset($setting->values)) {
            $values = json_decode($setting->values);
            $exts = $values->exts ?? 'gif|jpg|jpeg|png';
        }
        $exts = explode('|', $exts);
        if ($ext = substr(strrchr($file_name, '.'), 1)) {
            if (!in_array($ext, $exts)) {
                return $this->errMsg(1, '不允许的扩展名 ' . $ext);
            }
        }
        // 检查重复文件
        $new_path = str_replace(basename($path), '', $path) . $file_name;
        $check = DB::table('files')->where('path', $new_path)->first();
        if ($check && $check->path !== $new_path) {
            return $this->errMsg(1, '文件名重复');
        }
        $data['path'] = $new_path;
        if ($new_path !== $path) {
            if (Storage::exists($new_path)) return $this->errMsg(1, '文件已存在');
            Storage::move($path, $new_path);
            DB::table('files')->where('id', $id)->update($data);
        }
        return $this->errMsg(0, '修改成功');
    }

    public function del(Request $request)
    {
        $id = (array)$request->id;
        if (!$id) return $this->errMsg(1, '请选择数据');
        $db = DB::table('files')->whereIn('id', $id);
        // 删除存储的文件
        array_map(function ($item) {
            if (isset($item->path) && $item->path && Storage::exists($item->path))
                Storage::delete($item->path);
        }, $db->get()->all());
        $res = $db->delete();
        if (!$res) return $this->errMsg(1, '删除失败');
        return $this->errMsg(0, '删除成功');
    }

    // 上传
    public function uploads(Request $request)
    {
        // php artisan storage:link 创建符号链接
        if (!$request->hasFile('file')) $this->errMsg(1, '上传文件为空');
        $path = $request->file('file');
        // 检查上传类型
        $setting = DB::table('setting')->where('names', 'setting')->first();
        $exts = 'gif|jpg|jpeg|png';
        $size = 2048;
        if ($setting && isset($setting->values)) {
            $values = json_decode($setting->values);
            $exts = $values->exts ?? 'gif|jpg|jpeg|png';
            $size = $values->size ?? 2048;
        }
        $exts = explode('|', $exts);
        $ext = $path->extension();
        if (!in_array($ext, $exts)) {
            // 静默删除临时文件
            @unlink($path->getRealPath());
            $this->errMsg(1, '不允许的上传类型 ' . $ext);
        }
        // 检查文件大小
        $file_size = round(filesize($path->getRealPath()) / 1024 * 100) / 100;
        if ($file_size > (int)$size) {
            @unlink($path->getRealPath());
            $this->errMsg(1, '文件不能超过 ' . $size . ' KB');
        }
        if (preg_match('/(gif|jpg|jpeg|png|bmp|webp|psd|svg|tiff)$/i', $ext))
            $path = $path->store('/public/images');
        else
            $path = $path->store('/public/files');
        $url = Storage::url($path);
        // 附件信息保存文件管理
        $db = DB::table('files')->where('path', $path)->first();
        if (!$db)
            DB::table('files')->insert(['file_name' => basename($path), 'path' => $path, 'status' => 1, 'time' => time()]);
        return $this->errMsg(0, '上传成功', ['src' => $url, 'title' => basename($path)], ['file' => $url]);
    }
}
